#ifndef __WIZ_AI_ASTAR_PROXY_SHANHAOBO_19800429_HPP__
#define __WIZ_AI_ASTAR_PROXY_SHANHAOBO_19800429_HPP__

#include "./WizAIAStar.hpp"

namespace Wiz
{
    namespace AStar
    {
        namespace Proxy
        {
            template<class TopologyT>
            class Type
            {
            protected:
                typedef TopologyT                       tTopology;
                typedef tTopology &                     tTopologyRef;
                typedef tTopology const &               tTopologyIn;

                typedef ::Wiz::AStar::Node<tTopology>   tNode;
                typedef tNode*                          tNodePtr;
                typedef ::Wiz::Array::Type<tNodePtr>    tNodeArray;
                typedef tNodeArray&                     tNodeArrayOut;

                typedef Type                            tThis;

                typedef ::Wiz::Array::Type<tTopology>   tTopologyArray;
                typedef tTopologyArray&                 tTopologyArrayOut;

                typedef ::Wiz::Map::Type<tTopology, tNodePtr>
                                                        tNodeMap;

            protected:
                virtual tNodePtr            CreateNodeImpl(tTopologyIn InCandidate, ::Wiz::Real::In InG, ::Wiz::Real::In InH) const = WIZ_NULLPTR;
                virtual ::Wiz::Void::Type   DestoryNodeImpl(tNodePtr) const = WIZ_NULLPTR;

                virtual ::Wiz::Bool::Type   GetAllCandidate(tTopologyArrayOut, tTopologyIn) const = WIZ_NULLPTR;

                virtual ::Wiz::Bool::Type   IsValidCandidate(tTopologyIn) const = WIZ_NULLPTR;
                virtual ::Wiz::Bool::Type   CalcCandidate(::Wiz::Real::Out OutG, ::Wiz::Real::Out OutH, tNodePtr InParent) const = WIZ_NULLPTR;

            protected:
                ::Wiz::Void::Type Test(tNodeArrayOut OutNewNode, tNodePtr InParentPtr)
                {
                    tTopologyArray CandidateArray;
                    GetAllCandidate(CandidateArray, InParentPtr->m_Topology);

                    for (::Wiz::Int::Type i = 0; i < CandidateArray.Size(); ++i)
                    {
                        ::Wiz::Real::Type G, H;
                        tTopologyRef Candidate = CandidateArray[i];
                        if (IsValidCandidate(Candidate) && CalcCandidate(G, H, Candidate))
                        {
                            tNodePtr CandidateNodePtr = WIZ_NULLPTR;
                            tNodeMap::iterator itr = m_NodeMap.Find(Candidate);
                            if (itr == m_NodeMap.End())
                            {
                                CandidateNodePtr = CreateNodeImpl(Candidate, G, H);
                                if (::Wiz::IsValidPtr(CandidateNodePtr))
                                {
                                    m_NodeMap.Insert(Candidate, CandidateNodePtr);
                                    OutNewNode.PushBack(CandidateNodePtr);
                                }
                            }
                            else
                            {
                                CandidateNodePtr = itr.GetValue();
                                if (::Wiz::IsValidPtr(CandidateNodePtr))
                                {
                                    ::Wiz::Real::Type F = G + H;
                                    if (F < CandidateNodePtr->m_F)
                                    {
                                        CandidateNodePtr->m_F = F;
                                    }
                                    if (CandidateNodePtr->IsInOpenSet() == ::Wiz::Bool::False)
                                    {
                                        OutNewNode.PushBack(CandidateNodePtr);
                                    }
                                }
                            }
                        }
                    }
                }

            protected:
                tNodeMap    m_NodeMap;
            };
        } /// end of namespace Proxy
    } /// end of namespace AStar
} /// end of namespace Wiz

#endif /*__WIZ_AI_ASTAR_PROXY_SHANHAOBO_19800429_HPP__*/
